/** LMA - lost model alarm firmware
 * Michael Shimniok http://www.bot-thoughts.com/
 */
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include "config.h"
#include "morse.h"
#include "beep.h"
#include "adc.h"

long seconds = 1;			// 2^32 = 4294967296 seconds = 7 weeks, way more than enough; int isn't enough
long pause = PERIOD;

void disableWatchdog();
void enableWatchdog();
void slowClock();


/** ATtiny13 Lost Model Alarm sounds morse code "W" (warning) after a preset delay, and after a further
 * delay, "SOS" (mayday). The program utilizes sleep mode to conserve battery power and disables peripherals
 * between beeps.  The program is originally designed for an ultra-light LMA for ultra micro (UM) models like
 * the Hobbyzone Champ, inspired by losing mine to wind. (I got it back but still)
 *
 * Michael Shimniok - http://www.bot-thoughts.com
 */
int main(int argc, char **argv)
{
	cli();
	disableWatchdog();

	initBuzzer();

#ifdef DEBUG
	initLED();
#endif

	// TODO: ATtiny13A, shut down Timer module: 
	// PRR |= _BV(PRTIM0);

	slowClock();

	initADC();

	readVoltage();

	beepNum(getVolts());
	_delay_ms(2000);

	enableWatchdog();

 	sei();


	while (1) {
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		sleep_mode();
	}
}



/** Watchdog interrupt handler.
 * This is the heart of the software; it handles periodic monitoring and beeping,
 * voltage checking, etc. When this isn't running, the chip is sleeping
 * to conserve battery.
 */
ISR(WDT_vect)
{
	static long period = PERIOD;

	seconds++;	// increment 'clock'

#ifdef DEBUG 
	dit();
#endif

	// Read voltage
	readVoltage();
	// Set cycle time based on voltage
	if (getVolts() < VOLT_LOW)
		period = PERIOD_LOW;

	// Beep "W" if WARN time exceeded
	// Beep "SOS" if SOS time exceeded
	if (++pause >= period) {
		pause = 0;
		if (seconds >= SOS_TIME) {
			sos();
		} else if (seconds >= WARN_TIME) {
			w();
		}
	}

    //ledOff();
	//beepOff();

	// re-enable WDT interrupt
	WDTCR |= _BV(WDTIE);

	return;
}

/** Disable the watchdog reset mode and interrupt mode */
void disableWatchdog()
{
	MCUSR &= ~_BV(WDRF);
	WDTCR |= _BV(WDE) | _BV(WDCE);
	WDTCR = 0x00;
}


/**	Enable watchdog interrupt, set prescaling to 1 sec.
 * This is what's responsible for calling the watchdog ISR
 */
void enableWatchdog()
{
	WDTCR |= _BV(WDTIE) | _BV(WDP2) | _BV(WDP1);
}


/** Slow down the MCU clock to a glacial 150kHz to further
 * conserve battery power
 */
void slowClock()
{
	CLKPR = _BV(CLKPCE);
	CLKPR = _BV(CLKPS2) | _BV(CLKPS1); // scale = /64
}
